#pragma once

/* 需要map */
#include <base.h>

#define APFSDS_ARGS_NR		4
#define APFSDS_ARGLIST		word_t arg0, word_t arg1, word_t arg2, word_t arg3
#define APFSDS_ARGLIST_USED	arg0, arg1, arg2, arg3
#define APFSDS_ARGLIST_P(p)	(p)->arg[0], (p)->arg[1], (p)->arg[2], (p)->arg[3]

typedef void apfsds_t;
typedef unsigned long word_t;
typedef word_t	apfsds_return_t;
typedef apfsds_return_t	(apfsds_func_t)(APFSDS_ARGLIST);

typedef struct apfsdsarg
{
	word_t arg[APFSDS_ARGS_NR];
} apfsds_arg_t;

typedef struct apfsdsreq
{
	apfsds_arg_t	args;
	apfsds_func_t	*func;
} apfsds_future_t;

#define __MAP_ARGS(arg)			(word_t)(arg)
#define __WRAP_ARGS(arg_name, ...)	word_t __##arg_name [APFSDS_ARGS_NR] = { __VA_ARGS__ };  apfsds_arg_t *arg_name = (apfsds_arg_t *)__##arg_name; _Static_assert(sizeof(__##arg_name) <= sizeof(apfsds_arg_t), "apfsds arg size wrong");
#define WRAP_ARGS(arg_name, ...)	__WRAP_ARGS(arg_name, MAPC(__MAP_ARGS, __VA_ARGS__))

/* #include <pthreadalt.h> 不应该在这里包含 */

/* 申请 */
apfsds_t *apfsds_create(void);
/* 销毁 */
void apfsds_destroy(apfsds_t *l);

/* 占用一个地方 得到一个请求记录体 */
apfsds_t *apfsds_init(void *ptr, size_t size);
/* 返回一个size大小内存 */
void *apfsds_destruct(apfsds_t *l);

/* 异步执行 */
__attribute__((nonnull (1, 2, 3))) apfsds_future_t *apfsds_fetch(apfsds_t *l, apfsds_func_t *func, apfsds_arg_t *args);
/* 异步执行快速路径，寄存器传参减少参数拷贝和读取开销 */
__attribute__((nonnull (1, 2))) apfsds_future_t *apfsds_fetch_fast(apfsds_t *l, apfsds_func_t *func, APFSDS_ARGLIST);

/* 阻塞式等待结果 */
__attribute__((nonnull (1, 2))) apfsds_return_t apfsds_wait(apfsds_t *l, apfsds_future_t *future);

/* 直接阻塞时执行(内部封装)，可能有参数拷贝的开销 */
__attribute__((nonnull (1, 2, 3))) apfsds_return_t apfsds_sync(apfsds_t *l, apfsds_func_t *func, apfsds_arg_t *args);
/* 寄存器传参的阻塞式执行 */
__attribute__((nonnull (1, 2))) apfsds_return_t apfsds_sync_fast(apfsds_t *l, apfsds_func_t *func, APFSDS_ARGLIST);

/* FIXME: 替换apfsds_sync看看能不能优化一点性能 */
#ifndef APFSDS_LIB_BUILD
	#define apfsds_sync(l, func, pargs)	apfsds_sync_fast(l, func, APFSDS_ARGLIST_P(pargs))
	#define apfsds_fetch(l, func, pargs)	apfsds_fetch_fast(l, func, APFSDS_ARGLIST_P(pargs))
#endif

/* 随机等待会不会好一点? */
/* 等待多个 */
#define __MAP_WAITALL(promise_future_tuple)		__ret[__idx++] = apfsds_wait promise_future_tuple; 
/* 等待多个future执行结果, 返回一个数组 */
#define apfsds_wait_all(ret_arr, ...) do{\
	apfsds_return_t *__ret = ret_arr;\
	word_t __idx = 0;\
	MAP(__MAP_WAITALL, __VA_ARGS__)\
	} while(0)

/* 乱序等待性能更好 */
/* 考虑使用repeat实现 duff's device */
// #define __REPEAT_WAITALL(i, promise_future_tuple)	__ret[i] = apfsds_wait promise_future_tuple; 

// #define apfsds_wait_all_shuffle(ret_arr, first_exec, ...) do{\
// 	apfsds_return_t *__ret = ret_arr;\
// 	word_t __idx = rand_seed % ;\
// 	MAP(__MAP_WAITALL, __VA_ARGS__)\
// 	} while(0)

/* 获得future */
#define apfsds_try(future)	(!future->flag)